package com.enterprise.support.utility;

import org.apache.log4j.PropertyConfigurator;

import javax.persistence.Basic;
import javax.persistence.MappedSuperclass;
import javax.persistence.Transient;
import java.io.Serializable;
import java.math.BigDecimal;
import java.util.*;


/**
 * Created by IntelliJ IDEA.
 * User: Zhanggaojiang
 * Date: 11-1-19
 * Time: 上午8:41
 * Email: z82422@gmail.com
 * Enterprise集成框架的 核心对象 , 很多地方都用到它
 * 该对象是 一个 数据封装模型
 * WEB 请求中的数据可以 通过 WebUtility.getInput() 转换为  Enterprise
 * Hibernate 的实体对象 也集成与 此对象
 */
@MappedSuperclass
public class Enterprise<K, T> extends LinkedHashMap<K, T> implements Serializable {
    static {
        PropertyConfigurator.configure(Enterprise.class.getResource("/config/log4j.properties"));
    }

    protected String enterprisename;

    public Enterprise() {
    }

    public Enterprise(String name) {
        this.enterprisename = name;
    }

    public Enterprise(Map entity) {
        super(entity);
    }

    public Enterprise(Enterprise entity) {
        super(entity);
    }


    public Enterprise(String enterprisename, Enterprise entity) {
        this.enterprisename = enterprisename;
        super.putAll(entity);
    }

    public Enterprise setPrimary() {
        set("primary", getLastKey());
        return this;
    }

    @Transient
    public Enterprise getEnterprise(String key) {
        return (Enterprise) get(key);
    }

    public Enterprise setMessage(String message) {
        set("message", message);
        return this;
    }
    @Transient
    public String getMessage() {
        return getString("message");
    }
    @Transient
    public String getEnterpriseName() {
        return this.enterprisename;
    }

    public Enterprise setEnterpriseName(String name) {
        this.enterprisename = name;
        return this;
    }


    //==================================================================================================================
    //GET SET方法   Start
    public Enterprise set(Object key, Object value) {
        super.put((K) key, (T) value);
        return this;
    }
    @Transient
    public Long getLongId() {
        return getLong("id");
    }
    @Transient
    public Integer getIntId() {
        return getInt("id");
    }
    @Transient
    public Integer getInteger(Object key) {
        return getInt(key);
    }
    @Transient
    public Integer getGreaterid() {
        return getInt("greaterid");
    }

    public void setGreaterid(Integer greaterid) {
        set("greaterid", greaterid);
    }
    @Transient
    public Integer getLessid() {
        return getInt("lessid");
    }

    public void setLessid(Integer lessid) {
        set("lessid", lessid);
    }

    @javax.persistence.Column(name = "`CREATE`")
    @Basic
    public Date getCreate() {
        return getDate("create");
    }

    public void setCreate(Date create) {
        set("create", create);
    }
    @Transient
    public Integer getInt(Object key) {
        Object o = get(key);
        if (o == null || o.toString().trim().equalsIgnoreCase("")) {
            return 0;
        }
        Class classType = o.getClass();
        if (classType == Integer.class) {
            return ((Integer) o).intValue();
        } else if (classType == Short.class) {
            return new Integer(((Short) o).shortValue());
        } else if (classType == Long.class) {
            return ((Long) o).intValue();
        } else if (classType == BigDecimal.class) {
            return ((BigDecimal) o).intValue();
        } else if (classType == String.class) {
            try {
                return Integer.parseInt(o.toString());
            } catch (Exception ex) {
                System.err.println(this + "，" + key + ":" + o + "，在转换为int型时异常");
                return 0;
            }
        }
        return 0;
    }
    @Transient
    public double getDouble(Object key) {
        Object o = get(key);
        if (o == null) return 0;
        Class classType = o.getClass();
        if (classType == java.lang.Double.class) {
            return ((Double) o).doubleValue();
        } else if (classType == java.lang.Float.class) {
            try {
                return (double) ((Float) o).floatValue();
            } catch (Exception e) {
                return 0;
            }
        } else if (classType == java.lang.String.class || classType == java.math.BigDecimal.class) {
            try {
                return Double.parseDouble(o.toString());
            } catch (Exception e) {
                return 0;
            }
        } else {
            return 0;
        }
    }
    @Transient
    public float getFloat(Object key) {
        Object o = get(key);
        if (o == null) return 0;
        Class classType = o.getClass();
        if (classType == java.lang.Float.class) {
            return ((Float) o).floatValue();
        } else if (classType == java.lang.String.class || classType == java.math.BigDecimal.class) {
            try {
                return Float.parseFloat(o.toString());
            } catch (Exception e) {
                return 0;
            }
        } else {
            return 0;
        }
    }
    @Transient
    public Long getLong(Object key) {
        Object o = get(key);
        if (o == null) return 0l;
        Class classType = o.getClass();
        if (classType == java.lang.Long.class) {
            return ((Long) o).longValue();
        } else if (classType == java.lang.Integer.class) {
            return (long) ((Integer) o).intValue();
        } else if (classType == java.lang.Short.class) {
            return (long) ((Short) o).shortValue();
        } else if (classType == BigDecimal.class) {
            return ((BigDecimal) o).longValue();
        } else if (classType == java.lang.String.class) {
            return Long.parseLong(o.toString());
        } else {
            return 0l;
        }
    }
    @Transient
    public short getShort(Object key) {
        Object o = get(key);
        if (o == null) return 0;
        Class classType = o.getClass();
        if (classType == java.lang.Short.class) {
            return ((Short) o).shortValue();
        } else if (classType == java.lang.String.class) {
            try {
                return Short.parseShort(o.toString());
            } catch (Exception e) {
                return 0;
            }
        } else {
            return 0;
        }
    }
    @Transient
    public boolean getBoolean(Object key) {
        Object o = get(key);
        if (o == null) return false;
        if (o.getClass().isInstance(new Boolean(true))) {
            return ((Boolean) o).booleanValue();
        } else if (o.getClass().isInstance(new String())) {
            try {
                return Boolean.parseBoolean(o.toString());
            } catch (Exception e) {
                return false;
            }
        } else {
            return false;
        }
    }
    @Transient
    public String getString(Object key) {
        Object o = null;
        try {
            o = get(key);
            return o == null ? null : o.toString();
        } catch (RuntimeException ex) {
            ex.printStackTrace();
            return "EException:" + ex.getMessage();
        } catch (Exception ex) {
            ex.printStackTrace();
            return "EException:" + ex.getMessage();
        }
    }
    @Transient
    public String getStringByTrim(String key) {
        String value = getString(key);
        return value == null ? "" : value.trim();
    }
    @Transient
    public BigDecimal getBigDecimal(Object key) {
        Object o = get(key);
        if (o == null) return new BigDecimal(0.0D);
        else return (BigDecimal) o;
    }
    @Transient
    public Date getDate(Object key) {
        Object o = null;
        try {
            o = get(key);
            return o == null ? null : (Date) o;
        } catch (Exception ex) {
            ex.printStackTrace();
            return null;
        }
    }
    @Transient
    public Set getSet(Object key) {
        Object o = null;
        try {
            o = get(key);
            return o == null ? null : (Set) o;
        } catch (Exception ex) {
            ex.printStackTrace();
            return null;
        }
    }
    @Transient
    public <Q> Q getEntity(String key, Class<Q> clazz) {
        return (Q) get(key);
    }
    @Transient
    public List getList(String key) {
        return (List) get(key);
    }


    @Transient
    public Date getStartDate() {
        Date startDate = DataFormat.StringFormtDate(getString("startDate"));
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(startDate);
        calendar.set(Calendar.HOUR, 0);
        calendar.set(Calendar.MINUTE, 0);
        calendar.set(Calendar.SECOND, 0);
        return calendar.getTime();
    }
    @Transient
    public Date getEndDate() {
        Date endDate = DataFormat.StringFormtDate(getString("endDate"));
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(endDate);
        calendar.set(Calendar.HOUR, 23);
        calendar.set(Calendar.MINUTE, 59);
        calendar.set(Calendar.SECOND, 59);
        return calendar.getTime();
    }

    //GET SET方法   End
    //==================================================================================================================


    // Tools Utility 方法
    //==================================================================================================================
    //获取最后一次 set 的键(Key)
    @Transient
    private String getLastKey() {
        Iterator iterator = this.keySet().iterator();
        String key = null;
        while (iterator.hasNext()) {
            key = iterator.next().toString();
        }
        return key;
    }
    @Transient
    public String getFilterHtml(String key) {
        return isEmpty(key) ? "" : Function.filterHtml(getString(key));
    }

    public String getClearHtml(String key) {
        return isEmpty(key) ? "" : Function.clearHtml(getString(key));
    }

    //属性 操作 辅助方法   End
    @Transient
    public String getStringByUtf8(String key) {
        try {
            return (isEmpty(key)) ? getString(key) : new String(getString(key).getBytes("ISO-8859-1"), "utf-8");
        } catch (Exception ex) {
            ex.printStackTrace();
        }
        return getString(key);
    }
    @Transient
    public String getStringByGbk(String key) {
        try {
            return (isEmpty(key)) ? getString(key) : new String(getString(key).getBytes("ISO-8859-1"), "gbk");
        } catch (Exception ex) {
            ex.printStackTrace();
        }
        return getString(key);
    }
    @Transient
    public Object getDefaultValue(String field, Object value) {
        if (isEmpty(field)) {
            return value;
        }
        return get(field);
    }
    @Transient
    public String getStringByDefaultValue(String field, String value) {
        if (isEmpty(field)) {
            return value;
        }
        return getString(field);
    }
    @Transient
    public String substring(String key, int start, String symbol) {
        return isEmpty(key) ? "" : Function.substring(getString(key), start, symbol);
    }
    @Transient
    public boolean isEmpty(String field) {
        return Validation.isEmpty(get(field));
    }
    @Transient
    public boolean isEmpty(String field, String eq) {
        return Validation.isEmpty(get(field), eq);
    }
    @Transient
    public boolean isNumber(String field) {
        return matches(field, "[0-9]*");
    }
    @Transient
    public boolean isList(String field) {
        return get(field) instanceof List;
    }
    @Transient
    public boolean isMap(String field) {
        return get(field) instanceof Map;
    }

    public boolean equals(String key, Object value) {
        return isEmpty(key) ? false : (get(key).toString().equalsIgnoreCase(value == null ? "" : value.toString()));
    }
    @Transient
    public boolean matches(String key, String regex) {
        return Validation.matches(get(key), regex);
    }
    @Transient
    public String getURLEncoder(String key) {
        return WebUtility.getURLEncoder(getString(key));
    }
    @Transient
    public boolean isEmail(String key) {
        return Validation.isEmail(getString(key));
    }
    @Transient
    public String getURLDecoder(String key) {
        return WebUtility.getURLDecoder(getString("key"));
    }

    @Override
    public void putAll(Map<? extends K, ? extends T> m) {
        if (!Validation.isEmpty(m)) {
            super.putAll(m);
        }
    }

    //属性 操作 辅助方法   End
    //==================================================================================================================

    @Override
    public boolean equals(Object target) {
        if (this == target) return true;
        if (target == null || getClass() != target.getClass()) return false;
        Map<String, Object> temp = (Map<String, Object>) this;
        Enterprise targetE = (Enterprise) target;
        if (this.getInt("id") != targetE.getInt("id")) return false;
        for (Map.Entry<String, Object> entry : temp.entrySet()) {
            if (entry.getValue() != null ? !entry.getValue().equals(targetE.get(entry.getKey())) : targetE.get(entry.getKey()) != null)
                return false;
        }
        return true;
    }

    @Override
    public int hashCode() {
        Map<String, Object> temp = (Map<String, Object>) this;
        int result = getInt("id");
        for (Map.Entry<String, Object> entry : temp.entrySet()) {
            if (!(null == entry.getKey()
                    || null == entry.getValue()
                    || entry.getValue() instanceof Enterprise
                    || entry.getValue() instanceof Collection
                    || entry.getValue() instanceof Set)) {
                result = 31 * result + entry.getValue().hashCode();
            }
        }
        return result;
    }

    public String toString() {
        Map<String, Object> temp = (Map<String, Object>) this;
        StringBuffer buf = new StringBuffer();
        Set fileds = super.keySet();
        buf.append("\n\t----------------[ Enterprise Result ]----------------");
        buf.append("\n\t\t    KEY\t\t|\t VALUE");
        buf.append("\n\t-----------------------------------------------------");
        for (Map.Entry<String, Object> entry : temp.entrySet()) {
            if ((null == entry.getKey())) continue;
            int fieldLength = entry.getKey().toString().length();
            buf.append("\n\t" + entry.getKey());
            for (int t = 0; t < 4 - (Math.max(1, (fieldLength / 4) + ((fieldLength % 4) > 2 ? 1 : 0))); t++) {
                buf.append("\t");
            }
            if (entry.getValue() instanceof Enterprise) {
                buf.append("|        Enterprise -> " + entry.getClass());
            } else if (entry.getValue() instanceof Collection) {
                buf.append("|        Collection	-> " + ((Collection) entry.getValue()).size());
            } else if (entry.getValue() instanceof Set) {
                buf.append("|        Set        -> " + ((Set) entry.getValue()).size());
            } else {
                buf.append("|        " + entry.getValue());
            }

        }
        return buf.append("\n\t-----------------------------------------------------").toString();
    }
}
